#include "keyword_filter.h"
#include "base_test.h"
#include <cstring>
#include <fstream>
#include <iostream>

FilterOper::FilterOper()
{
}
FilterOper::~FilterOper()
{

}
void FilterOper::Load( std::string file )
{
    std::ifstream in(file);
    std::string line;
    if(in)
    {
        while(std::getline(in,line))
        {
            auto str = line.c_str();
            int len = line.size();
            if(nodes == nullptr)
                nodes = new KeywordNode();
            auto tmp = nodes;
            for(int i = 0; i < len;i++)
            {
                int index = (int)str[i];

                if(tmp->nodes[index] == nullptr)
                    tmp->nodes[index] = new KeywordNode();
                tmp = tmp->nodes[index];
                tmp->ch =str[i];
            }
            tmp->end = true;
            tmp->length = len;
        }
    }
}

bool FilterOper::find(KeywordNode* node,const char* str)
{
    std::string name(str);
    int len = strlen(str);
    auto tmp = node;
    bool bret = false;
    for(int i = 0; i < len;i++)
    {
        int index = (int)str[i];
        tmp = tmp->nodes[index];
        if(tmp == nullptr)
        {
            tmp = node;
            continue;
        }
        if(tmp->end)
        {
            auto beg = i - tmp->length + 1;
            name.replace(beg,tmp->length,tmp->length,'*');
            bret = true;
            tmp = node;
            continue;
        }
    }
    if((tmp == nullptr || !(tmp->end)) && !bret )
        return false;
    std::cout<<name<<std::endl;
    return bret;
}
bool FilterOper::operator()( const char *str ) 
{
    RUNTIME
    return find(nodes,str);
    int len = strlen(str);
    auto tmp = nodes;
    for(int i = 0; i < len;i++)
    {
        if(tmp == nullptr)
            continue;
        if(tmp->end)
            return true;
        int index = (int)str[i];
        tmp = tmp->nodes[index];
    }
    if(tmp == nullptr || !(tmp->end))
        return false;
    return true;
}
bool FilterOper::DepShow(KeywordNode* node,bool& next,int dep)
{
    if(node == nullptr)
    {
        return false;
    }
    if(next)
    {
        for(int j = 0;j<dep;j++)
            std::cout<<"  ";
    }
    std::cout<<node->ch<<"-";
    next = false;
    bool ret = false;
    dep++;
    if(node->end)
    {
        std::cout<<"]"<<std::endl;
        next = true;
    }
    for(int i = 0; i<256;i++)
    {
        DepShow(node->nodes[i],next,dep);
    }
    return ret;
}
void FilterOper::Show()
{
    if(nodes == nullptr)
        return;
    for(int i = 0; i<256;i++)
    {
        bool next = true;
        DepShow(nodes->nodes[i],next,0);
    }
}
//-----------------------------------------
void FilterOper2rd::Load( std::string file )
{
    std::ifstream in(file);
    std::string line;
    if(in)
    {
        while(std::getline(in,line))
        {
            auto str = line.c_str();
            int len = line.size();
            if(nodes == nullptr)
                nodes = std::make_shared<KeywordNode2rd>();
            auto tmp = nodes;
            for(int i = 0; i < len;)
            {
                int length = 0;
                if((str[i] & 0x80) == 0)
                {
                    length = 1;
                }
                else
                { 
                    length = 3;
                }
                std::string key = line.substr(i,length);
                auto next = tmp->words.find(key);
                if(next == tmp->words.end())
                {
                    auto node = std::make_shared<KeywordNode2rd>();
                    node->word = key;
                    tmp->words.emplace(key,node);
                    tmp = node;
                }
                else
                {
                    tmp = next->second;
                }
                i += length;
            }
            tmp->end = true;
            tmp->length = len;
        }
    }
}
bool FilterOper2rd::DepShow(std::shared_ptr<KeywordNode2rd> node,bool& next,int dep)
{
    if(node == nullptr)
    {
        return false;
    }
    if(next)
    {
        for(int j = 0;j<dep;j++)
        {
            if((node->word[0] & 0x80) == 0) //TODO:这个优化用父节点的字符判断
            {
                std::cout<<" ";
            }
            else
                std::cout<<"  ";
        }
    }
    std::cout<<node->word;
    next = false;
    bool ret = false;
    dep++;
    if(node->end)
    {
        std::cout<<";"<<std::endl;
        next = true;
    }
    for(auto it = node->words.begin(); it != node->words.end();it++)
    {
        DepShow(it->second,next,dep);
    }
    return ret;
}
void FilterOper2rd::Show()
{
    if(nodes == nullptr)
        return;
    for(auto it = nodes->words.begin(); it != nodes->words.end();it++)
    {
        bool next = true;
        DepShow(it->second,next,0);
    }
}
bool FilterOper2rd::operator()(const char* str)
{
    RUNTIME
    return find(nodes,str);
}
bool FilterOper2rd::find(std::shared_ptr<KeywordNode2rd> node,const char* str)
{
    std::string name(str);
    int len = strlen(str);
    auto tmp = node;
    bool bret = false;
    for(int i = 0; i < len;)
    {
        int length = 0;
        if((str[i] & 0x80) == 0)
        {
            length = 1;
        }
        else
        { 
            length = 3;
        }
        std::string key = name.substr(i,length);
        auto next = tmp->words.find(key);
        if(next == tmp->words.end())
        {
            i += length;
            tmp = node;
            continue;
        }
        tmp = next->second;
        i += length;
        if(tmp->end)
        {
            auto beg = i - tmp->length;
            name.replace(beg,tmp->length,tmp->length,'*');
            bret = true;
            tmp = node;
            continue;
        }
    }
    if((tmp == nullptr || !(tmp->end)) && !bret )
        return false;
    std::cout<<name<<std::endl;
    return bret;
}

